use tracing_subscriber::field::debug;

/**
 * 语句与表达式的区别:
 * 表达式会产生值，语句不会
 * let x = 5 不会产生值，但5会（产生的值就是5）；
 * return 5 不会产生值，但add(5,6)会产生值
 */

use crate::token::{Token, TokenType};
use core::fmt;
use std::any::Any;
use std::sync::Arc;
//token_literal返回与其关联的词法单元的字面量,仅用于调试和测试
//to_string方法既可以调试时打印ast节点，也可以用来比较ast节点
pub trait Node {
    fn as_any(&self) -> &dyn Any;
    fn token_literal(&self) ->String ;
    fn to_string(&self) -> String;
}

// statement_node和expression_node仅包含占位方法,不是必须的
pub trait Statement: Node  {
    fn statement_node(&self);
}

impl fmt::Debug for dyn Statement {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Statement: {}", self.to_string())
    }
}
//statement_node和expression_node仅包含占位方法,不是必须的
pub trait Expression: Node{
    fn expression_node(&self);
}

impl fmt::Debug for dyn Expression {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        write!(f, "Expression: {}", self.to_string())
    }
}

// #[derive(Debug)]
pub struct Program {
    pub statements: Vec<Arc<dyn Statement>>,
}

impl Program{
    pub fn token_literal(&self) -> String{
        if self.statements.len() >0 {
            if let Some(s) = self.statements.get(0){
                s.token_literal()
            }else{
                "".to_string()
            }
        } else {
            "".to_string()
        }
    }

    pub fn to_string(&self) -> String{
        let mut str_buffer = String::new();
        for s in self.statements.iter(){
            // str_buffer.push_str(*s);
            str_buffer.push_str(s.as_ref().to_string().as_str());
        }
        str_buffer
    }
}

impl Node for Program{
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token_literal()
    }
    
    fn to_string(&self) -> String {
        self.to_string()
    }
}

// #[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Identifier{
    pub token: Token,
    pub value: String,
}

impl Node for Identifier {
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        self.value.clone()
    }
}

//标识符Identifier本身不产生值，但表达式Expression可以产生值，这里标识符Identifier作为表达式来处理，是为了保持简单
impl Expression for Identifier {
    fn expression_node(&self) {
        unimplemented!()
    }
}


#[derive(Debug)]
pub struct IntegerLiteral{
    pub token: Token,
    pub value: i64,
}

impl Node for IntegerLiteral {
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        self.token.literal.clone()
    }
}

//标识符IntegerLiterial本身不产生值，但表达式Expression可以产生值，这里标识符IntegerLiterial作为表达式来处理，是为了保持简单
impl Expression for IntegerLiteral {
    fn expression_node(&self) {
        unimplemented!()
    }
}

/*
*let语句形式: let <标识符> = <表达式>;
*/
// #[derive(Debug)]
pub struct LetStatement {
    pub token: Token,//token.let词法单元
    pub name: Option<Identifier>,
    pub value: Option<Arc<dyn Expression>>,
}

impl Statement for LetStatement {
    fn statement_node(&self) {
        unimplemented!()
    }
}

impl Node for LetStatement {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        // format!("let {} = {};", self.name.to_string(), self.value.to_string())
        let mut str_buffer = String::new();

    // 添加字符
        str_buffer.push_str(self.token_literal().as_str());
        str_buffer.push(' ');
        str_buffer.push_str(&self.name.as_ref().unwrap().to_string());
        str_buffer.push_str(" = ");

        match &self.value {
            None=>{println!("identifier is null");},
            Some(s)=>{
                str_buffer.push_str(s.as_ref().to_string().as_str());
            },
        }
        str_buffer.push_str(";");
        str_buffer.to_string()
        // str_buffer.push_str(self.value.as_ref().unwrap().as_ref().to_string().as_str());
        // unimplemented!()
    }
}

// #[derive(Debug)]
pub struct ReturnStatement {
    pub token: Token,//token.return词法单元
    pub value: Option<Arc<dyn Expression>>,
}

impl Statement for ReturnStatement {
    fn statement_node(&self) {
        unimplemented!()
    }
}

impl Node for ReturnStatement {
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        let mut str_buffer = String::new();
        str_buffer.push_str(self.token_literal().as_str());
        str_buffer.push(' ');
        match &self.value{
            Some(v)=>{
                str_buffer.push_str(v.as_ref().to_string().as_str())
            },
            None=>{

            }
        }
        str_buffer.push(';');
        str_buffer
        // unimplemented!()
    }
}

// #[derive(Debug)]
// pub struct IfStatement {
//     pub token: Token,//token.if词法单元
//     pub value: Option<Box<dyn Expression>>,
// }

// impl Statement for IfStatement {
//     fn statement_node(&self) {
//         unimplemented!()
//     }
// }

// impl Node for IfStatement {
//     fn as_any(&self) -> &dyn Any {
//         self
//     }
//     fn token_literal(&self) -> String {
//         self.token.literal.clone()
//     }
    
//     fn to_string(&self) -> String {
//         // format!("return {};", self.value.to_string())
//         let mut str_buffer = String::new();
//         str_buffer.push_str(self.token_literal().as_str());
//         str_buffer.push(' ');
//         match &self.value{
//             Some(v)=>{
//                 str_buffer.push_str(v.as_ref().to_string().as_str())
//             },
//             None=>{

//             }
//         }
//         str_buffer.push(';');
//         str_buffer
//         // unimplemented!()
//     }
// }

/**
 * 表达式结构体ExpressionStatement
 * 表达式语句不是真正的语句，而是仅由表达式构成的语句，相当于一层封装
 * 如：let x = 5; 是let语句；x + 10 ; 是表达式语句
 */
// #[derive(Debug)]
pub struct ExpressionStatement{
    pub token: Token, //该表达式中的第一个词法单元
    pub expression: Option<Arc<dyn Expression>>,
}

impl Node for ExpressionStatement {
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }

    fn to_string(&self) -> String {
        self.expression.as_ref().unwrap().to_string()
    }
}

impl Statement for ExpressionStatement{
    fn statement_node(&self) {
        unimplemented!()
    }
}

//PrefixExpression节点有两个字段operator和right值得注意。operator是包含“-”或者“!”的字符串，right字段包含运算符右边的表达式
// #[derive(Debug)]
pub struct PrefixExpression{
    pub token: Token,
    pub operator: String,
    pub right: Option<Arc<dyn Expression>>,
}

impl Expression for PrefixExpression{ 
    fn expression_node(&self) {
        unimplemented!()
    }
}

impl Node for PrefixExpression{
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        let mut str_buffer = String::new();
        str_buffer.push('(');
        str_buffer.push_str(self.operator.as_str());
        str_buffer.push_str(self.right.as_ref().unwrap().to_string().as_str());
        str_buffer.push(')');
        str_buffer.to_string()
    }
}

#[derive(Debug)]
 pub struct InfixExpression{
    pub token: Token,
    pub left: Option<Arc<dyn Expression>>,
    pub operator: String,
    pub right: Option<Arc<dyn Expression>>,
}

impl Expression for InfixExpression{ 
    fn expression_node(&self) {
        unimplemented!()
    }
}

impl Node for InfixExpression{
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        let mut str_buffer = String::new();
        str_buffer.push('(');
        str_buffer.push_str(self.left.as_ref().unwrap().to_string().as_str());
        str_buffer.push_str(self.operator.as_str());
        str_buffer.push_str(self.right.as_ref().unwrap().to_string().as_str());
        str_buffer.push(')');
        str_buffer.to_string()
    }
}

pub struct BoolLiteral{
    pub token: Token,
    pub value: bool,
}

impl Node for BoolLiteral {
    fn as_any(&self) -> &dyn Any {
        self
    }

    fn token_literal(&self) ->String {
        self.token.literal.clone()
    }

    fn to_string(&self) -> String {
        self.token.literal.clone()
    }
}

impl Expression for BoolLiteral  {
    fn expression_node(&self) {
        unimplemented!()
    }
}

#[derive(Debug)]
pub struct IfExpression{
    pub token: Token,
    pub condition: Option<Arc<dyn Expression>>,
    pub consequence: Option<BlockStatement>,
    pub alternative: Option<BlockStatement>,
}

impl Expression for IfExpression{ 
    fn expression_node(&self) {
        unimplemented!()
    }
}

impl Node for IfExpression{
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        let mut str_buffer = String::new();
        str_buffer.push_str("if");
        str_buffer.push_str(&self.condition.as_ref().unwrap().to_string());
        str_buffer.push_str( " ");
        str_buffer.push_str(&self.consequence.as_ref().unwrap().to_string());
        if let Some(alt) = self.alternative.as_ref(){
            str_buffer.push_str("else");
            str_buffer.push_str(&alt.to_string());
        }
        str_buffer.to_string()
    }
}

#[derive(Debug)]
pub struct BlockStatement{
    pub token: Token,
    pub statements: Vec<Arc<dyn Statement>>,
}

impl Node for BlockStatement {
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }

    fn to_string(&self) -> String {
        let mut str_buffer = String::new();
        for stmt in &self.statements{
            str_buffer.push_str(&stmt.as_ref().to_string());
        }
        str_buffer.to_string()
    }
}

impl Statement for BlockStatement{
    fn statement_node(&self) {
        unimplemented!()
    }
}

#[derive(Debug)]
pub struct FunctionLiteral{
    pub token: Token,
    pub params: Option<Vec<Identifier>>,
    pub body: Option<BlockStatement>,
}

impl Expression for FunctionLiteral{ 
    fn expression_node(&self) {
        unimplemented!()
    }
}

impl Node for FunctionLiteral{
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }
    
    fn to_string(&self) -> String {
        let mut str_buffer = String::new();
        str_buffer.push_str("fn");
        str_buffer.push('(');
        let param = &**self.params.as_ref().unwrap();
        for i in 0..param.len(){
            if i == 0{
                str_buffer.push_str(param.get(i).unwrap().to_string().as_str());
            }else{
                str_buffer.push(',');
                str_buffer.push_str(param.get(i).unwrap().to_string().as_str());
            }
        }
        // for param in &**self.params.as_ref().unwrap(){
        //     str_buffer.push_str(param.to_string().as_str());
        //     str_buffer.push(',');
        // }
        str_buffer.push_str("){");
        str_buffer.push_str(self.body.as_ref().unwrap().to_string().as_str());
        str_buffer.push('}');
        str_buffer.to_string()
    }
}

//表达式调用,形如: add(2,3) 或 add(2+2, 3*3*3),调用表达式的结构如下:
//<表达式>(<以逗号分隔的表达式列表>)
pub struct CallExpression{
    pub token: Token,
    pub function: Arc<dyn Expression>,
    pub arguments: Vec<Arc<dyn Expression>>,
}

impl Expression for CallExpression{ 
    fn expression_node(&self) {
        unimplemented!()
    }
}

impl Node for CallExpression{
    fn as_any(&self) -> &dyn Any {
        self
    }
    fn token_literal(&self) -> String {
        self.token.literal.clone()
    }

    fn to_string(&self) -> String {
        let mut str_buffer = String::new();
        str_buffer.push_str(self.function.to_string().as_str());
        str_buffer.push('(');
        for i in 0..self.arguments.len(){
            let a = self.arguments.get(i).unwrap().as_ref();
        // for a in &self.arguments{
            if i == 0{
                str_buffer.push_str(a.to_string().as_str());
            }else{
                str_buffer.push(',');
                str_buffer.push_str(a.to_string().as_str());
            }
        }
        str_buffer.push(')');
        str_buffer.to_string()
    }
}
